src/group.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- safeGroupInit
- safeGroup
- blddir
- safePath
- getServerGroup
- setGroupDir
- setGD
- setGroup
- attachGroupTalk
- attachGroup
- authGroup
- CMDgroup
- int_comp
- printListgroup
- CMDlistgroup
/* $Id: group.c,v 1.2 1998/08/02 20:35:00 proff Exp $
* $Copyright$
*/
#include "nglobal.h"
#include "filesystem.h"
#include "xover.h"
#include "acc.h"
#include "group.h"
/* this isn't as lame L1 cache wise as one might think, because the hits are
* (excluding iso characters) between elements 97 and 122, with the exception
* of 46 ('.'). the strspn we were using was O((m*n/2)^2). We could use
* a bitmap, but the the extra shifts and masks remove all benefit gained by the
* 32 byte foot-print.
*/
static n_u8 safe_group[256]; /* this is expanded from conf->safeGroup at startup */
EXPORT void safeGroupInit (char *s)
/* [<][>][^][v][top][bottom][index][help] */
{
n_u8 *p = (n_u8*)s;
bzero (safe_group, sizeof safe_group);
for (; *p; p++)
safe_group[*p] = 1;
}
EXPORT bool safeGroup (char *s)
/* [<][>][^][v][top][bottom][index][help] */
{
n_u8 *p = (n_u8*)s;
for (; *p; p++)
if (!safe_group[*p])
return FALSE;
return TRUE;
}
/*
* recursively build directory hierarchy, starting at leaf
*/
EXPORT bool blddir (char *name)
/* [<][>][^][v][top][bottom][index][help] */
{
char *p;
if ((p = strrchr (name, '/')) == NULL)
return FALSE;
*p = '\0';
if (mkdir (name, (mode_t) 0775) == -1)
{
if (!blddir (name))
{
*p = '/';
return FALSE;
}
if (mkdir (name, (mode_t) 0775) == -1)
{
if (errno != EEXIST)
{
loge (("error building directory hierarchy %s", name));
*p = '/';
return FALSE;
}
}
}
Stats->groupsCached++;
*p = '/';
return TRUE;
}
EXPORT bool safePath (char *s)
/* [<][>][^][v][top][bottom][index][help] */
{
if (strstr(s, "../"))
return FALSE;
return TRUE;
}
EXPORT struct server_cfg *getServerGroup (char *group)
/* [<][>][^][v][top][bottom][index][help] */
{
struct group_cfg *gcf = NULL, *gcf2 = NULL;
for (gcf = GroupList; gcf; gcf = gcf->next)
if (matchExp (gcf->group_pat, group, 1, 0))
gcf2 = gcf;
if (!gcf2)
return NULL;
return gcf2->server_cfg;
}
/*
* chdir to correct group directory. we need to know
* the server host also, as it is used as the second
* level directory. if group is NULL, then
* we goto the second level dir and no lower
*/
EXPORT bool setGroupDir (char *group, struct server_cfg *scfg)
/* [<][>][^][v][top][bottom][index][help] */
{
char dir[MAX_PATH];
if (!scfg)
return FALSE;
if (group)
{
strExchange(group, '.', '/');
sprintf(dir, "%.127s/%.255s", scfg->host, group);
} else
strcpy(dir, scfg->host);
if (group)
strExchange(group, '/', '.');
if (strEq(dir, CurrentDir))
return TRUE;
if (chdir(con->cacheDir)==-1)
{
loge (("chdir(\"%s\") failed!", con->cacheDir));
return FALSE;
}
if (chdir(dir)==-1)
{
if (mkdir(dir, (mode_t)0775) == -1 &&
blddir(dir) && mkdir(dir, (mode_t)0775) == -1)
goto bad;
if (chdir(dir)==-1)
{
bad:
loge (("chdir(\"%s\") failed", dir));
return FALSE;
}
logd (("cwd now %s", dir));
}
strcpy(CurrentDir, dir);
return TRUE;
}
EXPORT bool setGD ()
/* [<][>][^][v][top][bottom][index][help] */
{
return setGroupDir (CurrentGroup, CurrentGroupScfg);
}
EXPORT void setGroup (struct newsgroup *n, int cnt, int lo, int hi)
/* [<][>][^][v][top][bottom][index][help] */
{
bool f_changed = FALSE;
if (n->msgs != cnt)
{
n->msgs = cnt;
f_changed = TRUE;
}
if (cnt != 0)
{
if (n->lo_server != lo)
{
n->lo_server = lo;
f_changed = TRUE;
}
if (n->hi_server != hi)
{
n->hi_server = hi;
f_changed = TRUE;
}
}
if (f_changed)
n->group_change_time = time(NULL); /* XXX syscall overhead */
}
/*
* set current group. we can be called by the socket.c routines, so we avoid using
* C*emit routines.
*/
EXPORT bool attachGroupTalk (char *group, struct newsgroup *n, struct server_cfg *scfg, bool send_client)
/* [<][>][^][v][top][bottom][index][help] */
{
char buf[MAX_LINE];
int hi, lo, msgs;
int cc;
fprintf (scfg->fh, "group %s\r\n", group);
if (fflush (scfg->fh)!=0 ||
!(cc=Cfget (scfg, buf, sizeof buf)))
{
scfg->share->group_fail++;
if (send_client)
emitrn (NNTP_SERVERTEMPDOWN);
return FALSE;
}
if (strToi (buf) != NNTP_GROUPOK_VAL)
{
if (send_client)
emit (buf);
scfg->share->group_fail++;
return FALSE;
}
if (sscanf (buf, "%*d %d %d %d", &msgs, &lo, &hi) == 3)
{
if (newsgroupLockWrite(n))
{
n->group_time = time(NULL);
setGroup(n, msgs, lo, hi);
n->write_locks = 0;
}
}
hi = getHi(n);
lo = getLo(n);
scfg->artno = lo;
if (send_client)
emitf ("%d %d %d %d %s\r\n", NNTP_GROUPOK_VAL, n->msgs, lo, hi, group);
if (!scfg->group || !strEq(scfg->group, group))
{
if (scfg->group)
free(scfg->group);
scfg->group = Sstrdup(group);
}
if (!scfg->group_actual || !strEq(scfg->group_actual, group))
{
if (scfg->group_actual)
free(scfg->group_actual);
scfg->group_actual = Sstrdup(group);
logd (("current newsgroup on server '%s' now '%s'", scfg->host, group));
}
scfg->share->group_good++;
return TRUE;
}
EXPORT bool attachGroup (char *group, bool sendclient)
/* [<][>][^][v][top][bottom][index][help] */
{
int hi, lo, msgs, gt = 0; /* stop gcc whinging */
struct newsgroup *n;
char *group_orig;
struct server_cfg *scfg=getServerGroup(group);
struct server_cfg *cf;
if (!scfg)
{
emitrn (NNTP_NOSUCHGROUP);
return FALSE;
}
if (!scfg || !(n=newsgroup_find_add(group, NULL, FALSE)))
{
emitrn (NNTP_NOSUCHGROUP);
return FALSE;
}
group_orig=scfg->group;
if (!setGroupDir(group, scfg))
{
#ifdef READ_LOCKS
n->read_locks--;
#endif
emitf ("%d setGroupDir(%s, %s) failed\r\n", NNTP_PERM_VAL, group, scfg->host); /* don't use NNTP_NOSUCHGROUP here */
return FALSE;
}
lo = getLo(n);
hi = getHi(n);
msgs = n->msgs;
gt = n->group_time;
#ifdef READ_LOCKS
n->read_locks--;
#endif
if (lo && hi)
{
if (GroupNextNoCache)
{
GroupNextNoCache = FALSE;
}
else
{
if (time(NULL) - gt < scfg->group_timeout)
{
if (sendclient)
emitf ("%d %d %d %d %s\r\n", NNTP_GROUPOK_VAL, msgs, lo, hi, group);
if (scfg->group)
free(scfg->group);
scfg->group = Sstrdup(group);
goto good;
}
}
}
scfg->group = NULL; /* stop attachServer setting the group */
cf=attachServer (scfg);
scfg->group = group_orig;
if (!cf)
{
emitrn (NNTP_SERVERTEMPDOWN);
return FALSE;
}
if (!attachGroupTalk(group, n, scfg, sendclient))
{
if (!sendclient)
emitrn (NNTP_SERVERTEMPDOWN);
return FALSE;
}
good:
CurrentGroupNode = n;
CurrentGroupArtNum = getLo(n);
CurrentGroupScfg = CurrentScfg = scfg;
strcpy (CurrentGroup, group);
return TRUE;
}
/*
* TODO: stress test this
*/
EXPORT struct authent *authGroup (char *attempted_group, bool output)
/* [<][>][^][v][top][bottom][index][help] */
{
struct authent *gp;
gp = authorise (RemoteHosts, attempted_group);
if (gp && gp->auth && AuthState != valid && gp->read)
{
if (output)
{
log (("%s not permitted read access to %s [missing credentials]", ClientHost, attempted_group));
emitrn (NNTP_NOSUCHGROUP);
}
return NULL;
}
if (!gp || !gp->read || gp->deny)
{
if (output)
{
log (("%s not permitted read access to %s", ClientHost, attempted_group));
emitrn (NNTP_NOSUCHGROUP);
}
return NULL;
}
return gp;
}
EXPORT bool CMDgroup (char *args)
/* [<][>][^][v][top][bottom][index][help] */
{
char attempted_group[MAX_GROUP + 20];
struct server_cfg *scfg;
struct authent *auth = NULL;
if (sscanf (args, "%*s %127[^\r\n \t]", attempted_group) != 1)
{
emitrn (NNTP_SYNTAX_USE);
return FALSE;
}
GroupsEntered++;
if (CurrentGroupArtRead && CurrentGroupScfg && CurrentGroupScfg->group)
loginn (("%s group %s %d", ClientHostNormal,
CurrentGroupScfg->group, CurrentGroupArtRead));
CurrentGroupArtRead = 0;
if (!safeGroup(attempted_group))
{
emitrn (NNTP_NOSUCHGROUP);
return FALSE;
}
if (!(scfg = getServerGroup (attempted_group)))
{
emitrn (NNTP_NOSUCHGROUP);
return FALSE;
}
if (con->groupSecurity || con->contentFilters)
{
auth=authGroup (attempted_group, TRUE);
if (!auth && con->groupSecurity)
{
CS->auth_blocked++;
return FALSE;
}
}
if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;
if (auth)
{
ME=363> if (attachGroup (attempted_group, TRUE))
{
CurrentGroupAuth = auth;